//
//  TargetType+Cache.swift
//  XNetwork_Example
//
//  Created by x on 2024/8/9.
//  Copyright © 2024 CocoaPods. All rights reserved.
//

import Moya
import RxSwift
import UIKit

public typealias CachingKey = StoringKey

/// 联合协议
public typealias Cacheable = Storable & StoringKey & Expirable

/// 拓展默认过期时间
public extension Expirable {
    var expiry: Expiry {
        return .never
    }
}

public extension TargetType where Self: Cacheable, Self.ResponseType == Moya.Response {
    
    func onCache<C: Codable>(_ type: C.Type, atKeyPath keyPath: String? = nil, using decoder: JSONDecoder = .init(), _ closure: (C) -> Void) -> OnCache<Self, C> {
        
        if let obj = try? cacheResponse().map(C.self, atKeyPath: keyPath, using: decoder) {
            closure(obj)
        }
        return OnCache(target: self, keyPath: keyPath, decoder: decoder)
    }
}


public extension TargetType where Self: Cacheable, Self.ResponseType == Moya.Response {
    // .cache.request(),发出自己走 Observable+Cache 里面的request
    var cache: Observable<Self> {
        Observable.just(self)
    }
    
    func cacheResponse() throws -> Moya.Response {
        let expiry = try self.expiry(for: self)
        
        guard expiry.isExpiry else {
            let response = try cachedResponse(for: self)
            return Response(statusCode: response.statusCode, data: response.data)
        }
        
        throw Expiry.Error.expired(expiry.date)
    }
    
    
    func storeCachedResponse(_ cachedResponse: Moya.Response) throws {
        try storeCachedResponse(cachedResponse, for: self)
        update(expiry: expiry, for: self)
    }
    
    func removeCachedResponse() throws {
        try removeCachedResponse(for: self)
        
        removeExpiry(for: self)
    }
}
